package org.xmap.ui.control;

import java.util.Enumeration;
import java.util.Hashtable;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

import org.xmap.app.Env;
import org.xmap.ui.Theme;
import org.xmap.ui.UIUtil;
import org.xmap.ui.ViewManager;
import org.xmap.ui.base.Event;
import org.xmap.ui.base.Window;

public final class List extends ListBase {

    private boolean showExtend;
    private int width1 = 30;
    private int width2 = 30;
    private int width3 = 100;

    private static String cutString(String original, int width) {
        int w = Env.instance.defaultFont.stringWidth(original);
        if (w <= width) {
            return original;
        }
        int base = width / 20;
        int i = 0;
        for (i = base; i <= original.length(); i++) {
            String sub = original.substring(0, i);
            int tmp = Env.instance.defaultFont.stringWidth(sub);
            if (tmp > width) {
                break;
            }
        }
        return original.substring(0, i);
    }

    public List(int leftUpX, int leftUpY, int width, int height, int orient) {
        super(leftUpX, leftUpY, width, height, orient);
        this.disCount = (height / Env.instance.defaultFontHeight) - 1;
        if (height % this.spacing != 0) {
            this.disCount++;
        }
        this.disOffset = 0;
        this.spacing = Env.instance.defaultFontHeight;
//        this.showTitle = true;
//        this.setclipBeforeDraw = true;
        super.setSetClipBeforeDraw(true);
        super.setShowTitle(true);
        this.showExtend = false;
    }

    public List(int width1, int width2, int width3, int leftUpX, int leftUpY, int width, int height, int orient) {
        this(leftUpX, leftUpY, width, height, orient);
        this.width1 = width1;
        this.width2 = width2;
        this.width3 = width3;
    }

    public void addContent(int id, Object obj,
                           Object first1, Object first2,
                           Object second1, Object second2,
                           Object third1, Object third2, boolean isHighlight) {
        if (first1 != null && first1 instanceof String) {
            first1 = List.cutString((String) first1, this.width1);
        }
        if (first2 != null && first2 instanceof String) {
            first2 = List.cutString((String) second1, this.width1);
        }
        Object tmp = second1;
        if (second1 != null && second1 instanceof String) {
            second1 = List.cutString((String) second1, this.width2);
        }
        if (second2 != null && second2 instanceof String) {
            second2 = List.cutString((String) second2, this.width2);
        }
        if (third1 != null && third1 instanceof String) {
            third1 = List.cutString((String) third1, this.width3);
        }
        if (third2 != null && third2 instanceof String) {
            third2 = List.cutString((String) third2, this.width3);
        }
        ListItem i = new ListItem(id, obj, first1, first2, second1, second2, third1, third2, isHighlight);
        i.objReserv = tmp;
        this.content.addElement(i);
        if (this.index == -1) {
            this.index = 0;
            this.pressSelectedIndex = index;
            this.disOffset = 0;
        }
        if (this.content.size() == 1 && this.itemListener != null) {
            this.notifyItemListener();
        }
        this.cellHeightInStrollbar = (this.getRect().height - 2) / this.content.size();
    }

    public void insertContent(int index, int id, Object obj,
                              Object first1, Object first2,
                              Object second1, Object second2,
                              Object third1, Object third2, boolean isHighlight) {
        if (first1 != null && first1 instanceof String) {
            first1 = List.cutString((String) first1, this.width1);
        }
        if (first2 != null && first2 instanceof String) {
            first2 = List.cutString((String) second1, this.width1);
        }
        Object tmp = second1;
        if (second1 != null && second1 instanceof String) {
            second1 = List.cutString((String) second1, this.width2);
        }
        if (second2 != null && second2 instanceof String) {
            second2 = List.cutString((String) second2, this.width2);
        }
        if (third1 != null && third1 instanceof String) {
            third1 = List.cutString((String) third1, this.width3);
        }
        if (third2 != null && third2 instanceof String) {
            third2 = List.cutString((String) third2, this.width3);
        }
        ListItem i = new ListItem(id, obj, first1, first2, second1, second2, third1, third2, isHighlight);
        i.objReserv = tmp;
        this.content.insertElementAt(i, index);
        if (this.index == -1) {
            this.index = 0;
            this.disOffset = 0;
            this.pressSelectedIndex = index;
        }
        this.notifyItemListener();
        this.cellHeightInStrollbar = (this.getRect().height - 2) / this.content.size();
    }

    public void setWidth1(int width1) {
        this.width1 = width1;
    }

    public void setWidth2(int width2) {
        this.width2 = width2;
    }

    public void setWidth3(int width3) {
        this.width3 = width3;
    }

    public void changeContentThird(Object obj, String third) {
        if (third != null) {
            third = List.cutString(third, this.width3);
        }
        for (int i = 0; i < this.content.size(); i++) {
            ListItem li = (ListItem)this.content.elementAt(i);
            if (li.obj == obj) {
                li.third1 = third;
                break;
            }
        }
    }

    public void removeContent(Object obj) {
        Object o = this.getSelectObj();
        if (o == obj) {
            this.removeSelected();
        } else {
            for (int i = 0; i < this.content.size(); i++) {
                ListItem li = (ListItem)this.content.elementAt(i);
                if (li.obj == obj) {
                    this.content.removeElement(li);
                    if (i < this.drawBase) {
                        this.drawBase--;
                    }
                    if (i >= this.drawBase && i < (this.drawBase + this.index)) {
                        this.index--;
                    }
                    if (i > (this.drawBase + this.index) && i < (this.drawBase + this.disCount - 1)) {
                        // do nothing
                    }
                    if (i > this.drawBase + this.disCount) {
                        // do nothing
                    }
                    if (this.content.size() > 0) {
                        this.cellHeightInStrollbar = (this.getRect().height - 2) / this.content.size();
                    }
                    break;
                }
            }
        }
    }

    public void showExtend(boolean show) {
        this.showExtend = show;
    }

    public void updateSecond2(Hashtable ht) {
        Enumeration e = this.content.elements();
        while (e.hasMoreElements()) {
            ListItem li = (ListItem) e.nextElement();
            String name = (String) ht.get(li.objReserv);
            String second2 = null;
            if (name == null) {
                second2 = (String) li.objReserv;
            } else {
                second2 = name;
            }
            li.second2 = List.cutString(second2, this.width2);
        }
    }

    public boolean pointerEvent(Event ev) {
        boolean result = false;
        switch (ev.type) {
        case Event.POINTER_PRESSED:
            if (this.getRect().collideWith(ev.param1, ev.param2)) {
                super.setPointerSelected(true);
                this.pointerPressedY = ev.param2; // 记录触笔的垂直位置
                int y = ev.param2 - this.getRect().leftUp.y - (this.showTitle ? this.getTitleHeight() : 0) /* - this.disOffset*/;
                if (this.adjust) {
                    y -= this.disOffset;
                }
                int curIndex = y / this.spacing;
                if (curIndex >= 0 && curIndex < Math.min(this.disCount, this.content.size())) {
                    this.index = curIndex;
                    if (this.viewHeight % this.spacing != 0) {
                        if (this.index == 0) {
                            this.disOffset = 0;
                        } else if (this.index == (this.disCount - 1)) {
                            if (!this.showTitle) {
                                this.disOffset = -(this.spacing - (this.viewHeight % this.spacing));
                            }
                        }
                    }
                    if (!super.getFocus()) {
                        if (this.owner != null) {
                            this.owner.requestGetFocus(this);
                        }
                    }
                    if (this.itemListener != null) {
                        ListItem li = (ListItem)this.content.elementAt(this.getSelectIndex());
                        this.itemListener.pointerSelected(li.id, li.obj);
                    }
                } else {
                    if (!super.getFocus()) {
                        if (this.owner != null) {
                            this.owner.requestGetFocus(this);
                        }
                    }
                }
                ViewManager.instance.requestRepaint();
                result = true;
            }
            break;
        case Event.POINTER_RELEASED:
            if (super.getPointerSelected()) {
                super.setPointerSelected(false);
                if (this.getRect().collideWith(ev.param1, ev.param2)) {
                    int y = ev.param2 - this.getRect().leftUp.y - (this.showTitle ? this.getTitleHeight() : 0) /* - this.disOffset*/;
                    if (this.adjust) {
                        y -= this.disOffset;
                    }
                    int curIndex = y / this.spacing;
                    if (curIndex >= 0 && curIndex < Math.min(this.disCount, this.content.size()) && this.index == curIndex) {
                        ListItem li = (ListItem)this.content.elementAt(this.getSelectIndex());
                        if (this.itemListener != null) {
                            if (super.pressSelectedIndex == curIndex) {
                                this.itemListener.pointerDoubleSelected(li.id, li.obj);
                            }
                            int distance = ev.param2 - this.pointerPressedY;
                            if (distance < 3 || distance > -3) {
                                this.itemListener.fireSelected(li.id, li.obj);
                            }
                        }
                    }
                    super.pressSelectedIndex = this.getDisplayIndex();
                }
                result = true;
            }
            break;
        case Event.POINTER_DRAGGED:
            if (super.getPointerSelected()) {
                if (this.getRect().collideWith(ev.param1, ev.param2)) {
                    int y = ev.param2 - this.pointerPressedY;
                    if (Math.abs(y) > (this.spacing >> 1)) { // 触笔上下移动
                        this.pointerPressedY = ev.param2;
                        if (y > 0) {
                            this.upOper();
                        } else {
                            this.downOper();
                        }
                    }
                    result = true;
                }
            }
            break;
        }
        return result;
    }

    public void draw(Graphics g) {

        g.setFont(Env.instance.defaultFont);
        g.setColor(this.bgColor);
        g.fillRect(0, 0, this.getRect().width, this.getRect().height);

        if (Theme.instance.listBackgroundImage != null) {
            g.drawImage(Theme.instance.listBackgroundImage, 0, 0, Graphics.LEFT | Graphics.TOP);
        }

        int base = this.showTitle ? this.titleHeight : 0;
        g.setColor(Theme.instance.listLineColor);
        if (this.adjust) {
            base += this.disOffset;
        }
        g.drawLine(0, base - 1, this.getRect().width, base - 1);
        for (int i = 0; i + this.drawBase < this.content.size() && i < this.disCount; i++) {
            if (i == this.index) {
                g.setColor(Theme.instance.listSelectedBackgroundColor);
                g.fillRect(0, base, this.getRect().width, this.spacing - 1);
            }
            ListItem item = (ListItem)this.content.elementAt(i + this.drawBase);
            if (item != null) {
                int rowMid = base + (this.spacing >> 1);
                base += this.spacing;
                if (!item.isHighlight) {
                    g.setColor(Theme.instance.listTextColor);
                } else {
                    g.setColor(Theme.instance.listHighLightTextColor);
                }
                if (this.showNumber) {
                    int h = this.drawBase + i + 1;
                    if (h <= 9) {
                        UIUtil.draw(g, "0" + h, 1, rowMid, Graphics.LEFT, Graphics.VCENTER);
                    } else {
                        UIUtil.draw(g, String.valueOf(h), 1, rowMid, Graphics.LEFT, Graphics.VCENTER);
                    }
                }
                if (!this.showExtend) {
//                    g.setClip(0, 0, this.width1, this.getRect().height);
                    this.drawItem(item.first1, g, this.columnX1, rowMid, this.columnAnchor1);
//                    g.setClip(0, 0, this.getRect().width, this.getRect().height);
                    this.drawItem(item.second1, g, this.columnX2, rowMid, this.columnAnchor2);
//                    g.setClip(this.getRect().width - this.width3, 0, this.width3, this.getRect().height);
                    this.drawItem(item.third1, g, this.columnX3, rowMid, this.columnAnchor3);
                } else {
//                    g.setClip(0, 0, this.width1, this.getRect().height);
                    this.drawItem(item.first2, g, this.columnX1, rowMid, this.columnAnchor1);
//                    g.setClip(0, 0, this.getRect().width, this.getRect().height);
                    this.drawItem(item.second2, g, this.columnX2, rowMid, this.columnAnchor2);
//                    g.setClip(this.getRect().width - this.width3, 0, this.width3, this.getRect().height);
                    this.drawItem(item.third2, g, this.columnX2, rowMid, this.columnAnchor3);
                }
                g.setColor(Theme.instance.listLineColor);
                g.drawLine(0, base - 1, this.getRect().width, base - 1);
            }
        }
        // 最后绘制标题
        if (this.showTitle) {
            g.setColor(Theme.instance.listLineColor);
            g.drawLine(0, 0, this.getRect().width, 0);
            g.drawLine(0, this.titleHeight - 1, this.getRect().width, this.titleHeight - 1);
            g.setColor(Theme.instance.listTextColor);
            if (this.titleName1 != null) {
                switch (this.titleAnchor1) {
                case Window.ALIGN_LEFT:
                    UIUtil.draw(g, this.titleName1, this.titleX1, this.titleHeight >> 1, Graphics.LEFT, Graphics.VCENTER);
                    break;
                case Window.ALIGN_CENTER:
                    UIUtil.draw(g, this.titleName1, this.titleX1, this.titleHeight >> 1, Graphics.HCENTER, Graphics.VCENTER);
                    break;
                case Window.ALIGN_RIGHT:
                    UIUtil.draw(g, this.titleName1, this.titleX1, this.titleHeight >> 1, Graphics.RIGHT, Graphics.VCENTER);
                    break;
                }
            }
            if (this.titleName2 != null) {
                switch (this.titleAnchor2) {
                case Window.ALIGN_LEFT:
                    UIUtil.draw(g, this.titleName2, this.titleX2, this.titleHeight >> 1, Graphics.LEFT, Graphics.VCENTER);
                    break;
                case Window.ALIGN_CENTER:
                    UIUtil.draw(g, this.titleName2, this.titleX2, this.titleHeight >> 1, Graphics.HCENTER, Graphics.VCENTER);
                    break;
                case Window.ALIGN_RIGHT:
                    UIUtil.draw(g, this.titleName2, this.titleX2, this.titleHeight >> 1, Graphics.RIGHT, Graphics.VCENTER);
                    break;
                }
            }
            if (this.titleName3 != null) {
                switch (this.titleAnchor3) {
                case Window.ALIGN_LEFT:
                    UIUtil.draw(g, this.titleName3, this.titleX3, this.titleHeight >> 1, Graphics.LEFT, Graphics.VCENTER);
                    break;
                case Window.ALIGN_CENTER:
                    UIUtil.draw(g, this.titleName3, this.titleX3, this.titleHeight >> 1, Graphics.HCENTER, Graphics.VCENTER);
                    break;
                case Window.ALIGN_RIGHT:
                    UIUtil.draw(g, this.titleName3, this.titleX3, this.titleHeight >> 1, Graphics.RIGHT, Graphics.VCENTER);
                }
            }
        }

        int y1 = 0;
        int y2 = 0;
        if (this.content.size() == 0 || this.content.size() <= this.disCount) {
            y1 = 1;
            y2 = this.getRect().height - 2;
        } else {
            y1 = this.drawBase * this.cellHeightInStrollbar;
            if (this.drawBase + this.disCount == this.content.size()) {
                y2 = this.getRect().height - 1;
            } else {
                y2 = (this.drawBase + this.disCount) * this.cellHeightInStrollbar;
            }
        }

        g.setColor(Theme.instance.explorerStrollbarBackgroundColor);
        g.fillRect(this.getRect().width - 4, 0, 4, this.getRect().height);
        g.setColor(Theme.instance.explorerStrollbarColor);
        g.fillRect(this.getRect().width - 3, y1, 2, y2 - y1 + 1);
    }

    private void drawItem(Object item, Graphics g, int x, int y, int anchor) {
        if (item != null) {
            if (item instanceof String) {
                UIUtil.draw(g, (String) item, x, y,
                            this.getMidpAnchor(anchor), Graphics.VCENTER);
            } else if (item instanceof Image) {
                g.drawImage((Image) item, x, y,
                            this.getMidpAnchor(anchor) | Graphics.VCENTER);
            } else if (item instanceof DrawableItem) {
                Object obj = ((DrawableItem) item).getDrawableItem();
                if (obj != null) {
                    if (obj instanceof String) {
                        UIUtil.draw(g, (String) obj, x, y,
                                    this.getMidpAnchor(anchor), Graphics.VCENTER);
                    } else if (obj instanceof Image) {
                        g.drawImage((Image) obj, x, y,
                                    this.getMidpAnchor(anchor) | Graphics.VCENTER);
                    }
                }
            }
        }
    }
}
